//package AQS;
//
//import java.util.concurrent.locks.Lock;

/**
 * @author shy_black
 * @date 2019/3/14 13:16
 * @Description:Acquire源码注释
 */
//AQS，即AbstractQueuedSynchronizer, 队列同步器，它是Java并发用来构建锁和其他同步组件的基础框架。
//
//        ```
//args代表的含义：
//		//独占式 args为null
//      static final Node EXCLUSIVE = null;
//       // 当前节点从同步队列中取消
//       static final int CANCELLED =  1;
//       //后继节点的线程处于等待状态，如果当前节点释放同步状态
//       会通知后继节点,使得后继 节点的线程继续运行。
//       static final int SIGNAL    = -1;
//      //节点在等待队列中，节点线程等待在Condition上，当其他线程对Condition调用了 signal()方法后，该节点将会从等待队列中转移到同步队列中，加入到对同步状态的获取中
//       static final int CONDITION = -2;
//      //表示下一次共享式同步状态获取将会无条件地被传播下去
//       static final int PROPAGATE = -3;
//```
//
//        AbstractQueuedSynchronizer
//        ```
//public abstract class AbstractQueuedSynchronizer
//    extends AbstractOwnableSynchronizer
//    implements java.io.Serializable {
//    ......
//    }
//```
//        获取锁过程：
//
//        ```
//public final void acquire(int arg) {
//		//如果tryAcquire（）不成功且
//		//acquireQueued（addWaiter（Node.EXCLUSIVE），arg）成功
//		//会调用selfInterrupt（）方法
//        if (!tryAcquire(arg) &&
//            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
//            selfInterrupt();
//    }
//```
//        下面我们进入if判断中的饿方法具体看一下获取锁的具体流程
//
//        ```
////如果tryAcquire（）方法传入参数不符合要求，会直接抛出异常
////如果成功获取到锁，返回true，否则返回false
//    protected boolean tryAcquire(int arg) {
//        throw new UnsupportedOperationException();
//    }
//```
//        addwaiter()方法，将未竞争到锁的线程包装成节点放入同步队列末端
//        ```
///**
//     * Creates and enqueues node for current thread and given mode.
//     *
//     * @param mode Node.EXCLUSIVE for exclusive, Node.SHARED for shared
//     * @return the new node
//     */
//    private Node addWaiter(Node mode) {
//    //将未竞争到锁的线程包装成节点，并标记清楚模式：
//    //是EXCLUSIVE（独占式）还是SHARED（共享式）
//        Node node = new Node(Thread.currentThread(), mode);
//        // Try the fast path of enq; backup to full enq on failure
//        Node pred = tail;
//        if (pred != null) {
//        //将node.prev指向双向链表的最后一个节点
//            node.prev = pred;
//            //使用CAS将node入队
//            if (compareAndSetTail(pred, node)) {
//                pred.next = node;
//                return node;
//            }
//        }
//        //如果CAS入队失败，调用enq（）方法进行入队操作
//        enq(node);
//        return node;
//    }
//```
//        enq()方法，如果未将node节点入队，则一直自旋进行CAS入队操作
//        ```
///**
//     * Inserts node into queue, initializing if necessary.
//     * See picture above.
//     * @param node the node to insert
//     * @return node's predecessor
//     */
//    private Node enq(final Node node) {
//        for (;;) {
//            Node t = tail;
//            //如果尾节点为空，说明同步队列此时为空队列
//            if (t == null) { // Must initialize
//            	//新建一个头结点，作为同步队列的头结点
//                if (compareAndSetHead(new Node()))
//                	//将使尾结点指向新创建的头结点
//                    tail = head;
//            } else {
//            	//如果尾节点不为空，说明同步队列现在有等待节点
//            	//node节点的前驱指针指向尾节点
//                node.prev = t;
//                //使用CAS将node尾插入同步队列
//                if (compareAndSetTail(t, node)) {
//                    t.next = node;
//                    return t;
//                }
//            }
//        }
//    }
//```
//        acquireQueued(final Node node, int arg){ }//请求队列
//        ```
///**
//     * Acquires in exclusive uninterruptible mode for thread already in
//     * queue. Used by condition wait methods as well as acquire.
//     *
//     * @param node the node
//     * @param arg the acquire argument
//     * @return {@code true} if interrupted while waiting
//     */
//    final boolean acquireQueued(final Node node, int arg) {
//    	//设置失败标志true
//        boolean failed = true;
//        try {
//        	//是否被interrupted标志 设置为false
//            boolean interrupted = false;
//            for (;;) {
//            	//因为在死循环中，所以相当于在从后向前遍历同步队列
//                final Node p = node.predecessor();
//                //如果p节点尾头结点，且获取锁成功
//                if (p == head && tryAcquire(arg)) {
//                	//设置node节点尾头结点
//                	//p节点赋为Head，thread赋为null，p.prev赋为null
//                	//相当于将p节点从同步队列中删除
//                    setHead(node);
//                    p.next = null; // help GC
//                    //failed标志位赋为false，双重否定表肯定，
//                    //意思大概为：距离头结点最近的合法节点获取锁成功并被出队
//                    failed = false;
//                    return interrupted;
//                }
//                if (shouldParkAfterFailedAcquire(p, node) &&
//                    parkAndCheckInterrupt())
//                    interrupted = true;
//            }
//        } finally {
//            if (failed)
//                cancelAcquire(node);
//        }
//    }
//```
//        shouldParkAfterFailedAcquire(Node pred, Node node)
//        单步目的：是尝试将前驱节点改为SIGNAL，表示此时当前节点应该被阻塞
//
//        放在循环中的语义：一直在acquireQueued()方法中自旋，直到将前驱节点状态置为SIGNAL，表示此时应当将当前节点阻塞
//        ```
//private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
//        int ws = pred.waitStatus;
//        if (ws == Node.SIGNAL)//singal == -1
//            /*
//             * This node has already set status asking a release
//             * to signal it, so it can safely park.
//             */
//            return true;
//        if (ws > 0) {//cancelled，取消状态
//            /*
//             * Predecessor was cancelled. Skip over predecessors and
//             * indicate retry.
//             */
//             //从后往前，寻找节点状态小于0的节点，即可以被park的节点
//            do {
//                node.prev = pred = pred.prev;
//            } while (pred.waitStatus > 0);
//            pred.next = node;
//        } else {
//            /*
//             * waitStatus must be 0 or PROPAGATE.  Indicate that we
//             * need a signal, but don't park yet.  Caller will need to
//             * retry to make sure it cannot acquire before parking.
//             */
//             //如果该节点的状态小于等于0，设置该节点状态为SIGNAL，
//            compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
//        }
//        //返回false，与&& 后的方法一起决定  是否    会阻塞当前线程
//        return false;
//    }
//```
//        parkAndCheckInterrupt()
//        前驱节点状态置为SINGAL后，将当前节点线程阻塞
//        放在循环中，语义为将shouldParkAfterFailedAcquire()中节点置为SINGAL
//        的线程节点阻塞
//        ```
//    /**
//     * Convenience method to park and then check if interrupted
//     *
//     * @return {@code true} if interrupted
//     */
//    private final boolean parkAndCheckInterrupt() {
//    	//阻塞节点线程
//        LockSupport.park(this);
//        return Thread.interrupted();
//    }
//```
//        独占式锁的释放： release（）
//
//        ```
//    public final boolean release(int arg) {
//        if (tryRelease(arg)) {
//        	//获取到当前队列的头结点
//        	//头结点
//            Node h = head;
//            if (h != null && h.waitStatus != 0)
//                unparkSuccessor(h);
//            return true;
//        }
//        return false;
//    }
//```
//        tryRelease
//        ```
//    protected boolean tryRelease(int arg) {
//        throw new UnsupportedOperationException();
//    }
//```
//        unparkSuccessor()//唤醒距离头结点最近的非空节点
//        ```
//   /**
//     * Wakes up node's successor, if one exists.
//     *
//     * @param node the node
//     */
//    private void unparkSuccessor(Node node) {
//        /*
//         * If status is negative (i.e., possibly needing signal) try
//         * to clear in anticipation of signalling.  It is OK if this
//         * fails or if status is changed by waiting thread.
//         */
//        int ws = node.waitStatus;
//       //CAS将头结点=状态置为0
//        if (ws < 0)
//            compareAndSetWaitStatus(node, ws, 0);
//
//        /*
//         * Thread to unpark is held in successor, which is normally
//         * just the next node.  But if cancelled or apparently null,
//         * traverse backwards from tail to find the actual
//         * non-cancelled successor.
//         */
//        Node s = node.next;
//        if (s == null || s.waitStatus > 0) {
//            s = null;
//            //当头结点的下一个节点为空时，
//            //从同步队列尾部开始一直向前找到距离头结点最近的一个非空节点
//            for (Node t = tail; t != null && t != node; t = t.prev)
//                if (t.waitStatus <= 0)
//                    s = t;
//        }
//        if (s != null)
//            LockSupport.unpark(s.thread);
//    }
//```
////